package com.enlorenz.common.geo.analyzer.distance;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.DateUtil;

import com.enlorenz.common.geo.base.IObject;
import com.enlorenz.common.geo.base.IStatus;
import com.enlorenz.core.base.IMessage;
import com.enlorenz.core.engine.manager.EngineManager;
import com.enlorenz.core.queue.proc.AbstractObjectCycleSleepThread;
import com.enlorenz.core.queue.transfer.imp.NoWaitMessageQueue;
import com.enlorenz.util.ReflectUtil;
import com.enlorenz.util.TimeUtil.TimeIntervalWrapper;

/**
 * 位置状态加载者
 * @author Karma
 *
 */
public abstract class AbstractStatusListLoader extends AbstractTimerEngine{
	//线程管理器
	private EngineManager engineManager;
	//开启线程数目
	private int threadNum=5;
	//休眠时间
	private long sleepTime=TimeConstants.SECOND_MILLI;
	//数据计算列表
	private List<IDataCalculator> dataCalcList;
	private List<AbstractObjectCycleSleepThread> threadList=new ArrayList<AbstractObjectCycleSleepThread>();
	private NoWaitMessageQueue queue=new NoWaitMessageQueue();
	
	public void setEngineManager(EngineManager engineManager) {
		this.engineManager = engineManager;
	}

	public void setThreadNum(int threadNum) {
		this.threadNum = threadNum;
	}

	public void setSleepTime(int sleepTime) {
		this.sleepTime = sleepTime;
	}

	public void setDataCalcList(List<IDataCalculator> dataCalcList) {
		this.dataCalcList = dataCalcList;
	}

	/**
	 * 初始化处理线程
	 * @throws Exception
	 */
	public void initThread() throws Exception{
		for(int i=0;i<threadNum;i++){
			AbstractObjectCycleSleepThread oct=new AbstractObjectCycleSleepThread() {
				@Override
				protected void process(IMessage result) {
					QueryTimeConditionMsg qtc=(QueryTimeConditionMsg)result;
					AbstractStatusListLoader.this.doObject(qtc);
				}
			};
			oct.setNoWaitMessageQueue(queue);
			oct.setSleepTime(sleepTime);
			oct.init();
			oct.start();
			threadList.add(oct);
		}
	}
	
	@Override
	protected void doProcess() throws Exception {
		Date nowDate=new Date();
		String startTime=DateUtil.getPreDayStartStr(nowDate);
		String endTime=DateUtil.getPreDayStartEnd(nowDate);
		String preDate=startTime.substring(0,8);
		
		List<IObject> objectList=getObjectList();
		if(PublicUtil.isListEmpty(objectList)){
			return;
		}
		doQueue(objectList,startTime, endTime, preDate);
	}
	
	protected void doQueue(List<IObject> objectList,String startTime,String endTime,String preDate){
		for(int i=0;i<objectList.size();i++){
			IObject object=objectList.get(i);
			QueryTimeConditionMsg msg=new QueryTimeConditionMsg();
			msg.setObjectId(object.getObjectId());
			msg.setStTime(startTime);
			msg.setEdTime(endTime);
			msg.setPreDate(preDate);
			msg.setObjectIndex(i);
			msg.setObjectTotal(objectList.size());
			queue.addMessage(msg);
		}
	}
	
	
	/**
	 * 进行区间处理
	 * @param stDate
	 * @param edDate
	 */
	public void doIntervalProc(String stDate,String edDate){
		List<TimeIntervalWrapper> list=DateUtil.getIntervalBetweenDate(stDate, edDate);
		
		List<IObject> objectList=getObjectList();
		if(PublicUtil.isListEmpty(objectList)){
			return;
		}
		for(TimeIntervalWrapper tw:list){
			doQueue(objectList,tw.getStTime(), tw.getEdTime(), tw.getDate());
		}
	}
	
	/**
	 * 开始处理实际数据
	 * @param msg
	 */
	protected void doObject(QueryTimeConditionMsg msg){
		logger.info("计算:["+msg.getObjectIndex()+"/"+msg.getObjectTotal()+"]["+msg.getPreDate()+"]"
				+msg.getObjectId()+"-"+msg.getStTime()+"-"+msg.getEdTime());
		//获取状态列表
		List<IStatus> statusList=queryStatusList(msg.getObjectId(),msg.getStTime(),msg.getEdTime());
		if(null == statusList){
			statusList=new ArrayList<IStatus>(0);
		}
		
		//拷贝一份处理器
		List<IDataCalculator> copyList=ReflectUtil.copy2NewList(dataCalcList);
		
		IStatus preStatus=null;
		for(int i=0;i<statusList.size();i++){
			IStatus status=statusList.get(i);
			//排除重复位置
			if(null!=preStatus
					&& preStatus.getStatusDateStr().equals(status.getStatusDateStr())){
				continue;
			}
			
			for(IDataCalculator dc:copyList){
				try{
					dc.doIterator(statusList.size(), i, status);
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
			
			preStatus=status;
		}
		
		//创建处理结果
		Map<String,String> result=createResultMap(msg,copyList);
		logger.info("计算结果:["+msg.getObjectIndex()+"/"+msg.getObjectTotal()+"]["+msg.getPreDate()+"]"
				+msg.getObjectId()+">>"+result);
		//处理结果
		doResult(result);
	}
	
	protected String getClaxxStr(Class claxx){
		return claxx.getSimpleName();
	}
	
	/**
	 * 创建结果Map
	 * @param copyList
	 * @return
	 */
	protected Map<String,String> createResultMap(QueryTimeConditionMsg msg,List<IDataCalculator> copyList){
		Map<String,String> resultMap=new LinkedHashMap<String, String>();
		resultMap.put("objectId", msg.getObjectId());
		resultMap.put("stTime", msg.getStTime());
		resultMap.put("edTime", msg.getEdTime());
		resultMap.put("preDate", msg.getPreDate());
		
		for(IDataCalculator dc:copyList){
			resultMap.put(getClaxxStr(dc.getClass()),dc.getResult());
		}
		return resultMap;
	}
	
	/**
	 * 处理结果
	 * @param resultMap
	 */
	protected abstract void doResult(Map<String,String> resultMap);
	
	
	/**
	 * 获取对象列表
	 * @return
	 */
	protected abstract List<IObject> getObjectList();
	
	/**
	 * 查询状态列表
	 * @param objectId
	 * @param stTime
	 * @param edTime
	 * @return
	 */
	protected abstract List<IStatus> queryStatusList(String objectId,String stTime,String edTime);
	
	
	@Override
	protected void onExceptionHappened(Exception e) {
	}

	@Override
	protected void onFinallyDo() {
	}
	
}
